<?php

namespace app\admin\controller;

use app\admin\model\OrderStateLog;
use app\admin\model\Technician;
use app\api\model\FareOrder;
use app\api\services\Refund;
use app\common\controller\Backend;
use think\facade\Db;
use think\facade\Log;
use Throwable;

/**
 * 订单管理管理
 */
class Order extends Backend
{
    /**
     * Order模型对象
     * @var object
     * @phpstan-var \app\admin\model\Order
     */
    protected object $model;
    protected array $noNeedPermission = ['*'];
    protected array|string $preExcludeFields = ['id', 'create_time'];

    protected string|array $quickSearchField = ['id'];
    protected array $withJoinTable = ['user', 'service', 'technician', 'refund', 'evaluate'];

    public function initialize (): void
    {
        parent::initialize();
        $this->model = new \app\admin\model\Order;
    }


    /**
     * 若需重写查看、编辑、删除等方法，请复制 @see \app\admin\library\traits\Backend 中对应的方法至此进行重写
     */

    /**
     * 查看
     * @throws Throwable
     */
    public function index (): void
    {
        if ($this->request->param('select')) {
            $this->select();
        }

        list($where, $alias, $limit, $order) = $this->queryBuilder();

        $service_total_price = $this->model
            ->alias('order')
            ->where($where)->where($this->isAgentWhere())->sum('service_total_price');
        $fare_price = $this->model
            ->alias('order')
            ->where($where)->where($this->isAgentWhere())->sum('fare_price');

        $service_total_price = bcsub($service_total_price, $fare_price, 2);

        $res = $this->model
            ->field($this->indexField)
            ->with($this->withJoinTable)
            ->where($this->isAgentWhere())
            ->alias($alias)
            ->where($where)
            ->order($order)
            ->paginate($limit)->each(function ($item) {
                $item->order_state_text = $item->order_state_text;
                if ($item->evaluate) {
                    $img = explode(',', $item->evaluate->img);
                    foreach ($img as &$v) {
                        $v = IMAGE_URL . $v;
                    }
                    unset($v);
                    $item->evaluate->img = $img;
                }
                $item->service_price_fare =  bcsub($item->service_total_price,$item->fare_price,2);
                return $item;
            });

        $this->success('', [
            'list'                => $res->items(),
            'total'               => $res->total(),
            'service_total_price' => $service_total_price,
            'fare_price'          => $fare_price,
            'remark'              => get_route_remark(),
        ]);
    }

    /**
     * TODO 待完善支付后取消 和技师上门中取消
     *  取消订单
     * @param int $order_id 订单ID
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function cancelOrder (): void
    {
        $order_id = (int)$this->request->param('order_id');
        if (empty($order_id)) {
            $this->error("order_id 为必填项");
        }

        $orderInfo = $this->model->where('id', $order_id)->find();

        if (!$orderInfo) {
            $this->error("订单不存在");
        }

        $state = ['ToBePaid', 'Paid', 'Received', 'SetOut', 'Reach'];

        if (!in_array($orderInfo->order_state, $state)) {
            $this->error("订单状态不允许取消");
        }


        #加事务
        Db::startTrans();
        try {

            if ($orderInfo->order_state != 'ToBePaid') {
                if ($orderInfo->order_state == 'SetOut' || $orderInfo->order_state == 'Reach') {
                    #查看技师出行是否免费
                    $is_travel = Technician::where('technician_id', $orderInfo->technician_id)->value('is_travel');
                    $fare_price = FareOrder::where('order_id', $orderInfo->id)->value('fare_price') ?? 0;
                    if ($is_travel == 0 && $fare_price == 0) {
                        $this->error('等待技师上传车费凭证');
                    }
                }
                #退款
                $refund = new Refund($orderInfo->order_sn, $orderInfo->payment_order_sn);
                $pay_way = $orderInfo->pay_way;
                $refund->$pay_way();
            }
            $orderInfo->order_state = 'Canceled';
            $orderInfo->save();

            #记录订单状态
            setOrderStateLog($orderInfo->id, 'Canceled');
            Db::commit();
        } catch (Throwable $e) {
            Db::rollback();
            Log::error('订单取消失败：user_id :' . $this->auth->id . ' order_id ' . $order_id . 'errMsg' . $e->getMessage());
            $this->error("订单取消失败", $e->getMessage());
        }

        $this->success("订单取消成功");
    }


    /**
     * 获取时间线
     * @return void
     */
    public function getTimeline (): void
    {
        $order_id = (int)$this->request->param('order_id');

        $ret = OrderStateLog::where('order_id', $order_id)->order('create_time', 'asc')->select();

        $stateAll = [
            'Paid'      => '已支付',
            'Received'  => '技师已接单',
            'SetOut'    => '技师已出发',
            'Reach'     => '技师已到达',
            'Start'     => '技师服务中',
            'Completed' => '已完成',
        ];

        $arr = [];
        foreach ($stateAll as $k => $v) {
            $arr[$k]['content'] = $v;
            $arr[$k]['timestamp'] = '状态未开始';
        }

        foreach ($ret as $v) {
            if (!isset($arr[$v->order_state])) {
                continue;
            }
            $arr[$v->order_state]['timestamp'] = $v->create_time;
            $arr[$v->order_state]['color'] = '#0bbd87';
            $arr[$v->order_state]['type'] = 'primary';
        }


        $this->success('', $arr);
    }

    /**
     * 获取附加-加钟订单信息
     * @return void
     */
    public function getAddClockOrder (): void
    {
        $order_sn = $this->request->param('order_sn');
        $ret = \app\admin\model\Order::where('association_order_sn', $order_sn)->column('order_sn');
        $this->success('', $ret);
    }

    /**
     * 获取附加-车费订单信息
     * @return void
     */
    public function getFareOrder (): void
    {
        $order_id = $this->request->param('order_id');
        $ret = FareOrder::where('order_id', $order_id)->find();
        if (!empty($ret)) {
            $arr = explode(',', $ret['fare_fare_price_imgs']);
            if (!empty($arr)) {
                foreach ($arr as &$v) {
                    $v = IMAGE_URL . $v;
                }
                unset($v);
            }
            $ret['fare_fare_price_imgs'] = $arr;
        }
        $this->success('', $ret);
    }
}